/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package xmlasm.action;

import com.opensymphony.xwork2.ActionContext;
import xmlasm.bo.FeedBO;
import xmlasm.sync.FilePathHolder;
import utils.XMLUtils;
import utils.XPathUtils;
import com.opensymphony.xwork2.ActionSupport;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpressionException;
import org.apache.struts2.ServletActionContext;
import org.w3c.dom.Node;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import utils.SimpleJSonObject;
import xmlasm.bo.UserBO;
import xmlasm.dto.Feed;
import xmlasm.dao.FeedDAO;
import xmlasm.dto.User;

/**
 *
 * @author Hoang
 */
public class FeedAction extends ActionSupport {

    private int rssID;
    //Se tra ve trang nao sau khi goi method addFeedtoUserList hoac remove
    private String returnTo;

    public String getReturnTo() {
        return returnTo;
    }

    public void setReturnTo(String returnTo) {
        this.returnTo = returnTo;
    }

    public int getRssID() {
        return rssID;
    }

    public void setRssID(int rssID) {
        this.rssID = rssID;
    }
    private String rssLink;
    private String rssName;
    private String rssDescription;

    public String getRssDescription() {
        return rssDescription;
    }

    public void setRssDescription(String rssDescription) {
        this.rssDescription = rssDescription;
    }

    public String getRssName() {
        return rssName;
    }

    public void setRssName(String rssName) {
        this.rssName = rssName;
    }
    private InputStream inputStream;

    public InputStream getInputStream() {
        return inputStream;
    }

    public String getRssLink() {
        return rssLink;
    }

    public void setRssLink(String rssLink) {
        this.rssLink = rssLink;
    }

    public String checkRSS() {
        SimpleJSonObject result = new SimpleJSonObject();

        //Thu tim xem feed da co trong file xml chua
        try {
            Feed findFeed = FeedBO.getRssFromRSSLink(rssLink);
            if (findFeed != null) {
                //Check xem user da co feed nay chua
                Map session = ActionContext.getContext().getSession();
                User user = (User) session.get("USER");
                if (findFeed.isOwnedByUser(user.getUserId())) {
                    result.put("message", "error");
                    result.put("errorInfo", "Bạn đã có feed này trong danh sách.");
                } else {
                    result.put("message", "success");
                    result.put("title", findFeed.getTitle());
                    result.put("description", findFeed.getDecription());
                }
            } else {
                try {
                    Document doc = XMLUtils.parseDom(rssLink);
                    Node titleNode = XPathUtils.selectSingleNode(doc, "//channel/title");
                    Node descriptionNode = XPathUtils.selectSingleNode(doc, "//channel/description");

                    //Neu ko the lay duoc, chung to link bi loi
                    if (titleNode == null && descriptionNode == null) {
                        throw new SAXException();
                    }

                    //Lay noi dung của 2 node đọc được từ rss
                    String title = titleNode == null ? "Không có" : titleNode.getTextContent();
                    String description = descriptionNode == null ? "Không có" : descriptionNode.getTextContent();
                    description = description.length() >= 100 ? description.substring(0, 95) + "..." : description;

                    result.put("message", "success");
                    result.put("title", title);
                    result.put("description", description);

                } catch (FileNotFoundException ex) {
                    //Catch cai nay khi link dan vao bi sai, ko doc duoc
                    result.put("message", "error");
                    result.put("errorInfo", "Đường dẫn tới feed không phù hợp.");
                } catch (XPathExpressionException ex) {
                    Logger.getLogger(FeedAction.class.getName()).log(Level.SEVERE, null, ex);
                } catch (ParserConfigurationException ex) {
                    Logger.getLogger(FeedAction.class.getName()).log(Level.SEVERE, null, ex);
                } catch (SAXException ex) {
                    //Catch cai nay khi doc đuoc link, nhưng link ko phai rss hoac rss bi loi
                    result.put("message", "error");
                    result.put("errorInfo", "Không thể đọc feed từ đường dẫn.");
                }
            }
            inputStream = new ByteArrayInputStream(result.toString().getBytes("UTF-8"));
        } catch (IOException ex) {
            Logger.getLogger(FeedAction.class.getName()).log(Level.SEVERE, null, ex);
            return ERROR;
        }
        return SUCCESS;
    }

    //Khi add, luon luon tao file moi
    public String insertFeed() {
        try {
            int dumpID = 0;
            //Insert feed vao xml o doan nay, sau do lay dumpID ra
            Feed findFeed = FeedBO.getRssFromRSSLink(rssLink);
            if (findFeed != null) {
                dumpID = findFeed.getFeedId();
            } else {
                dumpID = FeedDAO.insertFeed(this);
                FeedBO.insertFeedToXML(new Feed(dumpID, rssLink, rssName, rssDescription, new Date()));
                //Insert feed xong nho bo feed vao xml
            }

            //Tao 1 file de luu rss vua hot
            String rssFileName = "rss-" + dumpID + ".xml";
            String webPath = FilePathHolder.getInstance().getWebPath();

            //Lay path cua file do, tu cay dom ghi xuong xml
            String rssFilePath = webPath + "WEB-INF/" + rssFileName;

            //Lay duong dan file xls, dung xls de filter lan 1
            String xlsFirstPath = webPath + "WEB-INF/xsl/rssFirstPass.xsl";
            //Khong cong webPath vi se dung trong JSP
            String outputXMLPath = "WEB-INF/" + "rss-filtered-" + dumpID + ".xml";

            //Bat dau parse file rss
            Document doc = XMLUtils.parseDom(rssLink);
            XMLUtils.writeDOMtoXML(rssFilePath, doc);
            XMLUtils.doTransform(rssFilePath, xlsFirstPath, webPath + outputXMLPath);

            //Dua duong dan file moi tao vao request de goi trong jsp
            HttpServletRequest request = ServletActionContext.getRequest();
            request.setAttribute("outputXML", outputXMLPath);
            request.setAttribute("newID", dumpID);
            return SUCCESS;
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(FeedAction.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SAXException ex) {
            Logger.getLogger(FeedAction.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(FeedAction.class.getName()).log(Level.SEVERE, null, ex);
        }
        return ERROR;
    }

    //ham nay dung khi nguoi ta bam vao 1 link de xem feed cua link do
    //Khi xem feed link, bat dau check file da co ton tai hoac da lau
    public String readFeed() {
        HttpServletRequest request = ServletActionContext.getRequest();
        String webPath = FilePathHolder.getInstance().getWebPath();

        String rssFilePath = webPath
                + "WEB-INF/" + "rss-" + rssID + ".xml";
        //Khong cong webPath vi se dung trong JSP
        String outputXMLPath = "WEB-INF/" + "rss-filtered-" + rssID + ".xml";


        File f = new File(rssFilePath);
        Date date = new Date();
        //Neu file rss chua filter ko ton tai hoac file da qua 10p thi moi tao file va parsing
        if (!f.exists() || ((date.getTime() - f.lastModified()) > 10*60*1000)) {
            try {
                //Lay rssLink tu id
                String gotRssLink = FeedBO.getRSSLinkFromID(rssID);
                //Neu tim ko thay
                if (gotRssLink.equals("")) {
                request.setAttribute("ERROR", "Feed này ko tồn tại. Bạn vui lòng thử lại sau.");
                return ERROR;
                }

                Document doc = XMLUtils.parseDom(gotRssLink);
                XMLUtils.writeDOMtoXML(rssFilePath, doc);
                //Lay duong dan file xls, dung xls de filter lan 1
                String xlsFirstPath = webPath + "WEB-INF/xsl/rssFirstPass.xsl";
                XMLUtils.doTransform(rssFilePath, xlsFirstPath,
                        webPath + outputXMLPath);
            } catch (ParserConfigurationException ex) {          
                request.setAttribute("ERROR", ex.getMessage());
                return ERROR;
            } catch (SAXException ex) {           
                request.setAttribute("ERROR", ex.getMessage());
                return ERROR;
            } catch (IOException ex) {
                request.setAttribute("ERROR", ex.getMessage());
                return ERROR;
            }
        }

        //Dua duong dan file moi tao vao request de goi trong jsp
        request.setAttribute("outputXML", outputXMLPath);
        return SUCCESS;
    }

    public String addFeedToUserList() {
        HttpServletRequest request = ServletActionContext.getRequest();
        Map session = ActionContext.getContext().getSession();
        User user = (User) session.get("USER");
        int userID = user.getUserId();
        if (FeedDAO.setAssociation(userID, rssID)) {
            //ko can load va marshall lai
            // FeedBO.loadFeedsAndMarshall();
            FeedBO.setAssociationToXML(userID, rssID);
            return SUCCESS;
        }
        request.setAttribute("ERROR", "Không thể thêm feed này vào. Bạn vui lòng thử lại sau.");
        return ERROR;
    }

    public String removeFeedOfUser() {
        HttpServletRequest request = ServletActionContext.getRequest();
        Map session = ActionContext.getContext().getSession();
        User user = (User) session.get("USER");
        int userID = user.getUserId();
        if (FeedDAO.removeAssociation(userID, rssID)) {
            FeedBO.removeAssociationFromXML(userID, rssID);
            return SUCCESS;
        }
        request.setAttribute("ERROR", "Không thể xóa feed này. Bạn vui lòng thử lại sau.");
        return ERROR;
    }

    private String feedId;
    private String title;
    private String description;

    public String updateFeedList() {
        HttpServletRequest request = ServletActionContext.getRequest();
        int id = Integer.parseInt(feedId);
        Feed f = new Feed(id, title, description);
        boolean rs1 = FeedDAO.updateFeed(f);
        boolean rs2 = FeedBO.updateFeedXML(id, title, description);
        if (rs1 && rs2) {
            request.setAttribute("notify", "Cập nhật thành công");
            return SUCCESS;
        }
        request.setAttribute("ERROR", "Cập nhật thất bại");
        return ERROR;
    }

    public String deleteFeedList() {
        HttpServletRequest request = ServletActionContext.getRequest();
        int id = Integer.parseInt(feedId);
        boolean rs1 = FeedDAO.removeAssociation(id);
        boolean rs2 = FeedDAO.deleteFeed(id);
        boolean rs3 = FeedBO.deleteFeedFromXML(id);
        if (rs2 && rs3) {
            request.setAttribute("notify", "Đã xóa feed với ID: " + feedId);
            return SUCCESS;
        }
        request.setAttribute("ERROR", "Không thể xóa được feed");
        return ERROR;
    }

    public String validateJoinFeedUser() {

        //Neu chua co file user.xml, phai marshall file do ra moi join dc
        File f = new File(FilePathHolder.getInstance().getUserXMLPath());
        if (!f.exists()) {
            UserBO.loadUsersAndMarshall();
        }

        Map<String, String> xmlFile = new HashMap<String, String>();
        xmlFile.put("userXML", FilePathHolder.getInstance().getUserXMLPath());
        String webPath = FilePathHolder.getInstance().getWebPath();
        String xslFilePath = webPath + "WEB-INF/xsl/joinFeed-User.xsl";
        String outputXMLRelativePath = "WEB-INF/dataXML/feed-user.xml";


        File outputXML = new File(webPath + outputXMLRelativePath);
        HttpServletRequest request = ServletActionContext.getRequest();

        if (!outputXML.exists()) {
            XMLUtils.doTransform(FilePathHolder.getInstance().getFeedXMLPath(),
                    xslFilePath, webPath + outputXMLRelativePath, xmlFile);

            try {
                XMLUtils.validateXML(webPath + outputXMLRelativePath, webPath + "WEB-INF/schema/feed-user.xsd");
            } catch (SAXException ex) {
                request.setAttribute("ERROR", ex.getMessage());
                return ERROR;
            }
        }
        return SUCCESS;
    }

    private String outputFO;

    public String getFeedPDF() {
        String webPath = FilePathHolder.getInstance().getWebPath();
        String inputXML = webPath + "WEB-INF/dataXML/feed-user.xml";
        String inputXSL = webPath + "WEB-INF/xsl/feedFO.xsl";
        outputFO = webPath + "WEB-INF/pdf/fo/feedUser.fo";
        XMLUtils.doTransform(inputXML, inputXSL, outputFO);
        return SUCCESS;
    }

    /**
     * @return the feedId
     */
    public String getFeedId() {
        return feedId;
    }

    /**
     * @param feedId the feedId to set
     */
    public void setFeedId(String feedId) {
        this.feedId = feedId;
    }

    /**
     * @return the title
     */
    public String getTitle() {
        return title;
    }

    /**
     * @param title the title to set
     */
    public void setTitle(String title) {
        this.title = title;
    }

    /**
     * @return the description
     */
    public String getDescription() {
        return description;
    }

    /**
     * @param description the description to set
     */
    public void setDescription(String description) {
        this.description = description;
    }

    /**
     * @return the outputFO
     */
    public String getOutputFO() {
        return outputFO;
    }

    /**
     * @param outputFO the outputFO to set
     */
    public void setOutputFO(String outputFO) {
        this.outputFO = outputFO;
    }
}
